Lesson overview

Today we’re going to look at a few ways of improving on default ggplot2 graphics, as well as explore some other packages for plotting data. Specifically, we’re going to look at the cowplot package for tweaking our ggplot2 figures, and the ggtext package which allows for more advanced text formatting on our plots. Then we’ll produce interactive graphics via the plotly package. For this lesson we’ll need the built-in mtcars data set in addition to the gapminder data to test out these different plotting methods.

Load packages

Let’s start by loading the libraries we’ll need.

# install.packages(c("cowplot", "plotly", "ggtext", "tidyverse", "gapminder"))
library(cowplot)
library(plotly)
library(ggtext)
library(gapminder)
library(tidyverse)

data("mtcars")
mtcars <- mtcars %>% rownames_to_column("car")


Our first plot & themes

Let’s start by making a standard plot using ggplot2 to get our baseline.

ggplot(mtcars, aes(cyl, mpg)) +
  geom_point()


Let’s see how we can tweak this plot using the available methods. We’ll be making use of two functions here: labs() to create labels, and theme() to customize the appearance of our plot. Let’s change the axis labels, add a title, and change the overall theme with theme_bw().

ggplot(mtcars, aes(cyl, mpg)) +
  geom_point() +
  labs(
    x = "Number of Cylinders", 
    y = "Miles per Gallon", 
    title = "Comparing Engine Size and Fuel Efficiency"
  ) +
  theme_bw() +
  theme(axis.ticks = element_blank())


The theme_bw() function is acting as a “preset”, changing multiple arguments of the regular theme() function at once. There are some additional versions of theme_bw(), such as theme_classic(), and theme_grey() (the default of ggplot2). For theme() itself, there are a whole range of arguments that can be used to alter the appearance of the plot. Any argument you want to specify must be in the format of element_x() (like the element_blank() we used earlier). Let’s build on this example by increasing the font size, as the default is often too small.

ggplot(mtcars, aes(cyl, mpg)) +
  geom_point(size = 3, pch = 21, fill = "dodgerblue4", colour = "black") +
  labs(
    x = "Number of Cylinders", 
    y = "Miles per Gallon", 
    title = "Comparing Engine Size and Fuel Efficiency"
  ) +
  theme_bw() +
  theme(
    axis.ticks = element_blank(),
    axis.text = element_text(size = 12, colour = "black"),
    title = element_text(size = 14, colour = "dodgerblue4"),
    panel.grid.minor = element_blank()
  )


Now our plot looks a lot nicer!


Making use of cowplot

Another alternative to making a bunch of little changes ourselves is to use another package, cowplot. This package comes with suite of functions, but let’s start with theme_cowplot(), which makes a variety of changes to the default look of ggplot2 graphics.

ggplot(mtcars, aes(cyl, mpg)) +
  geom_point(size = 3, pch = 21, fill = "dodgerblue4", colour = "black") +
  labs(
    x = "Number of Cylinders", 
    y = "Miles per Gallon", 
    title = "Comparing Engine Size and Fuel Efficiency"
  ) +
  theme_cowplot()


Another really useful feature of the cowplot package is the ability to combine multiple plots into a multi-panel style figure using the plot_grid() function. Let’s test it out with an example.

mpg_cyl_plot <- ggplot(mtcars, aes(cyl, mpg)) +
  geom_point(size = 3, pch = 21, fill = "dodgerblue4", colour = "black") +
  labs(
    x = "Number of Cylinders", 
    y = "Miles per Gallon", 
    title = "Comparing Engine Size and Fuel Efficiency"
  ) +
  theme_cowplot()

disp_hp_plot <- ggplot(mtcars, aes(disp, hp)) +
  geom_smooth(method = "lm", colour = "grey") +
  geom_point(size = 3, pch = 21, fill = "tomato", colour = "black") +
  labs(
    x = "Displacement", 
    y = "Horse Power", 
    title = "Comparing Engine Size and Displacement"
  ) +
  theme_cowplot()

plot_grid(
  mpg_cyl_plot, disp_hp_plot, 
  nrow = 2, ncol = 1, align = "h", labels = "AUTO")


Customizing text with ggtext

The next package we’ll use, ggtext, allows us to format any text on our plots, using a bit of HTML. Let’s start with an example.

gapminder_filtered <- gapminder %>% 
  filter(country %in% c("Canada", "Germany", "France", "Australia")) %>% 
  mutate(country_continent = paste0(country, "<br><i>(", continent, ")</i>"))

ggplot(gapminder_filtered, aes(country_continent, pop, fill = country)) +
  geom_boxplot() +
  theme_cowplot() +
  theme(
    axis.text.x = element_markdown(),
    legend.position = "none"
  ) +
  labs(x = "Country", y = "Population")


Interactive plots with plotly

Now let’s move on to another plotting library, plotly. Unlike ggplot2, this package allows us to make interactive HTML plots. Let’s see what this looks like with an example. Note the syntax is a bit different then ggplot2, so pay close attention to how we set up our plot.

plot_ly(mtcars, x = ~cyl, y = ~mpg, type = "scatter", text = ~car) %>% 
  plotly::layout(
    title = "Comparing Engine Size and Fuel Efficiency",
    xaxis = list(title = "Number of Cylinders"),
    yaxis = list(title = "Miles per Gallons")
  )


As you can see, hovering our cursor over the points displays the coordinates as well as the name of the vehicle.
Let’s see how we can tweak this some more.

fit <- lm(mpg ~ cyl, data = mtcars)

plot_ly(mtcars, x = ~cyl, y = ~mpg, type = "scatter", text = ~car) %>% 
  add_lines(x = ~cyl, y = fitted(fit), line = list(color = "black")) %>% 
  plotly::layout(
    title = "Comparing Engine Size and Fuel Efficiency",
    xaxis = list(title = "Number of Cylinders"),
    yaxis = list(title = "Miles per Gallons")
  )


We can also extensively format the hover text displayed on the plot, using a bit of HTML language.

fit <- lm(mpg ~ cyl, data = mtcars)

plot_ly(mtcars, x = ~cyl) %>%
  add_trace(
    y = ~mpg, 
    mode = "markers", 
    marker = list(size = 10),
    hoverinfo = "text",
    text = ~paste0("<b>Car: </b>", car)
  ) %>% 
  add_trace(y = fitted(fit), mode = "lines") %>% 
  plotly::layout(
    title = "Comparing Engine Size and Fuel Efficiency",
    xaxis = list(title = "Number of Cylinders"),
    yaxis = list(title = "Miles per Gallons")
  )


Making a boxplot using plotly, specifying custom colours, and adding lines along the x and y axis.

plot_ly(mtcars, x = ~cyl) %>%
  add_boxplot(
    y = ~mpg, 
    marker = list(color = "black"),
    line = list(color = "black"), 
    fillcolor = "white"
  ) %>% 
  plotly::layout(
    title = "Comparing Engine Size and Fuel Efficiency",
    xaxis = list(showline = TRUE, 
                 title = "Number of Cylinders", 
                 titlefont = list(size = 14), 
                 tickfont = list(size = 14)),
    yaxis = list(showline = TRUE, 
                 title = "Miles per Gallons",
                 titlefont = list(size = 14), 
                 tickfont = list(size = 14))
  )